import * as fs from 'fs';
import * as path from 'path';
import { Logger } from '../../src/logger/Logger';

/**
 * 知识库检索器
 * 从学习的代码库中检索相关示例，增强生成质量
 */
export class KnowledgeRetriever {
    private knowledgeBasePath: string;
    private knowledge: any = null;
    private loaded: boolean = false;

    constructor() {
        this.knowledgeBasePath = path.join(__dirname, 'codebase-knowledge.json');
    }

    /**
     * 加载知识库
     */
    public async loadKnowledgeBase(): Promise<boolean> {
        if (this.loaded) {
            return true;
        }

        if (!fs.existsSync(this.knowledgeBasePath)) {
            Logger.warn('[KnowledgeRetriever] 知识库文件不存在，将使用默认模式');
            return false;
        }

        try {
            const data = fs.readFileSync(this.knowledgeBasePath, 'utf-8');
            this.knowledge = JSON.parse(data);
            this.loaded = true;
            
            Logger.info('[KnowledgeRetriever] ✅ 知识库加载成功');
            Logger.info(`[KnowledgeRetriever] 单元测试模式: ${this.getUnitTestPatternCount()}`);
            Logger.info(`[KnowledgeRetriever] Fuzz测试模式: ${this.getFuzzTestPatternCount()}`);
            
            return true;
        } catch (error) {
            Logger.error(`[KnowledgeRetriever] 加载知识库失败: ${error}`);
            return false;
        }
    }

    /**
     * 检索单元测试相关示例（用于增强 Prompt）
     */
    public retrieveUnitTestExamples(context: {
        functionName?: string;
        className?: string;
        subsystem?: string;
        sourceFilePath?: string;
    }): string {
        if (!this.loaded || !this.knowledge) {
            return '';
        }

        const patterns = this.findRelevantUnitTestPatterns(context);
        if (patterns.length === 0) {
            return '';
        }

        return this.buildUnitTestEnhancedPrompt(patterns);
    }

    /**
     * 检索 Fuzz 测试相关示例
     */
    public retrieveFuzzTestExamples(context: {
        sourceFilePath?: string;
        hasIPC?: boolean;
        className?: string;
    }): string {
        if (!this.loaded || !this.knowledge) {
            return '';
        }

        const patterns = this.findRelevantFuzzTestPatterns(context);
        if (patterns.length === 0) {
            return '';
        }

        return this.buildFuzzTestEnhancedPrompt(patterns);
    }

    /**
     * 检索 BUILD.gn 配置示例
     */
    public retrieveBuildConfigExamples(context: {
        testType: 'unittest' | 'fuzztest';
        subsystem?: string;
    }): string {
        if (!this.loaded || !this.knowledge) {
            return '';
        }

        const configs = this.findRelevantBuildConfigs(context);
        if (configs.length === 0) {
            return '';
        }

        return this.buildBuildConfigEnhancedPrompt(configs, context.testType);
    }

    /**
     * 检索 Mock 模式示例
     */
    public retrieveMockPatterns(): string {
        if (!this.loaded || !this.knowledge) {
            return '';
        }

        const mockPatterns = this.knowledge.mockPatterns;
        if (!mockPatterns || mockPatterns.length === 0) {
            return '';
        }

        return this.buildMockPatternsPrompt(mockPatterns);
    }

    // ===== 私有方法 =====

    private findRelevantUnitTestPatterns(context: any): any[] {
        const allPatterns: any[] = [];
        
        // 从所有项目中收集模式
        for (const [projectName, patterns] of this.knowledge.unitTestPatterns || []) {
            for (const pattern of patterns) {
                allPatterns.push({ projectName, ...pattern });
            }
        }

        // 简单的相关性评分
        const scored = allPatterns.map(pattern => {
            let score = 0;
            
            // 如果有类名匹配
            if (context.className && pattern.testClassName.toLowerCase().includes(context.className.toLowerCase())) {
                score += 10;
            }
            
            // 如果有函数名匹配
            if (context.functionName && pattern.testClassName.toLowerCase().includes(context.functionName.toLowerCase())) {
                score += 5;
            }
            
            // 使用 GMock 的优先
            if (pattern.usesGMock) {
                score += 2;
            }
            
            // 测试用例多的优先
            score += Math.min(pattern.testCaseCount, 5);
            
            return { pattern, score };
        });

        // 按分数排序，返回前3个
        return scored
            .sort((a, b) => b.score - a.score)
            .slice(0, 3)
            .map(item => item.pattern);
    }

    private findRelevantFuzzTestPatterns(context: any): any[] {
        const allPatterns: any[] = [];
        
        for (const [projectName, patterns] of this.knowledge.fuzzTestPatterns || []) {
            for (const pattern of patterns) {
                allPatterns.push({ projectName, ...pattern });
            }
        }

        // 相关性评分
        const scored = allPatterns.map(pattern => {
            let score = 0;
            
            // 如果需要 IPC，优先 MessageParcel
            if (context.hasIPC && pattern.hasMessageParcel) {
                score += 10;
            }
            
            // 有 Stub 实现的优先
            if (pattern.hasStubImpl) {
                score += 5;
            }
            
            // 有权限设置的优先
            if (pattern.hasAccessTokenSetup) {
                score += 3;
            }
            
            return { pattern, score };
        });

        return scored
            .sort((a, b) => b.score - a.score)
            .slice(0, 3)
            .map(item => item.pattern);
    }

    private findRelevantBuildConfigs(context: any): any[] {
        const allConfigs: any[] = [];
        
        for (const [projectName, configs] of this.knowledge.buildConfigs || []) {
            for (const config of configs) {
                allConfigs.push({ projectName, ...config });
            }
        }

        // 过滤匹配的类型
        const filtered = allConfigs.filter(config => {
            if (context.testType === 'unittest') {
                return config.hasOhosUnittest;
            } else {
                return config.hasOhosFuzztest;
            }
        });

        return filtered.slice(0, 3);
    }

    private buildUnitTestEnhancedPrompt(patterns: any[]): string {
        let prompt = '\n\n## 📚 从代码库中学习的单元测试最佳实践\n\n';
        prompt += `我已分析了 OpenHarmony 代码库中的 ${patterns.length} 个相关单元测试示例，以下是关键模式：\n\n`;

        for (let i = 0; i < patterns.length; i++) {
            const pattern = patterns[i];
            prompt += `### 示例 ${i + 1}：${pattern.testClassName} (来自: ${pattern.projectName})\n\n`;
            
            prompt += `**测试类结构：**\n`;
            prompt += `- ✅ SetUpTestCase: ${pattern.hasSetUpTestCase ? '是' : '否'}\n`;
            prompt += `- ✅ TearDownTestCase: ${pattern.hasTearDownTestCase ? '是' : '否'}\n`;
            prompt += `- ✅ 使用 HWTEST_F: ${pattern.usesHWTEST_F ? '是' : '否'}\n`;
            prompt += `- ✅ 使用 GMock: ${pattern.usesGMock ? '是' : '否'}\n`;
            prompt += `- ✅ 测试用例数: ${pattern.testCaseCount}\n\n`;
            
            if (pattern.includes.length > 0) {
                prompt += `**常用头文件：**\n`;
                prompt += pattern.includes.slice(0, 8).map((inc: string) => `- #include <${inc}>`).join('\n');
                prompt += '\n\n';
            }
            
            if (pattern.exampleSnippet) {
                prompt += `**代码片段：**\n\`\`\`cpp\n${pattern.exampleSnippet}\n\`\`\`\n\n`;
            }
        }

        prompt += '**请参考以上实际项目中的模式，生成符合 OpenHarmony 规范的高质量测试代码。**\n';
        
        return prompt;
    }

    private buildFuzzTestEnhancedPrompt(patterns: any[]): string {
        let prompt = '\n\n## 📚 从代码库中学习的 Fuzz 测试最佳实践\n\n';
        prompt += `我已分析了 OpenHarmony 代码库中的 ${patterns.length} 个相关 Fuzzer 示例，以下是关键模式：\n\n`;

        for (let i = 0; i < patterns.length; i++) {
            const pattern = patterns[i];
            prompt += `### Fuzzer 示例 ${i + 1}：${pattern.fuzzerName} (来自: ${pattern.projectName})\n\n`;
            
            prompt += `**技术特征：**\n`;
            prompt += `- ${pattern.hasMessageParcel ? '✅' : '❌'} 使用 MessageParcel\n`;
            prompt += `- ${pattern.hasFuzzedDataProvider ? '✅' : '❌'} 使用 FuzzedDataProvider\n`;
            prompt += `- ${pattern.hasStubImpl ? '✅' : '❌'} 包含 Stub 实现\n`;
            prompt += `- ${pattern.hasAccessTokenSetup ? '✅' : '❌'} 配置访问权限\n\n`;
            
            if (pattern.includes.length > 0) {
                prompt += `**关键头文件：**\n`;
                prompt += pattern.includes.slice(0, 6).map((inc: string) => `- #include "${inc}"`).join('\n');
                prompt += '\n\n';
            }
            
            if (pattern.exampleSnippet) {
                prompt += `**代码片段：**\n\`\`\`cpp\n${pattern.exampleSnippet}\n\`\`\`\n\n`;
            }
        }

        prompt += '**请严格参考以上经过验证的 Fuzzer 模式，确保生成的代码符合 OpenHarmony 标准。**\n';
        
        return prompt;
    }

    private buildBuildConfigEnhancedPrompt(configs: any[], testType: string): string {
        let prompt = '\n\n## 📚 从代码库中学习的 BUILD.gn 配置\n\n';
        prompt += `以下是 ${configs.length} 个真实项目中的 ${testType} BUILD.gn 配置示例：\n\n`;

        for (let i = 0; i < configs.length; i++) {
            const config = configs[i];
            prompt += `### BUILD.gn 示例 ${i + 1} (来自: ${config.projectName})\n\n`;
            
            prompt += `**module_out_path:** ${config.moduleOutPath}\n\n`;
            
            if (config.externalDeps.length > 0) {
                prompt += `**常用 external_deps:**\n`;
                prompt += config.externalDeps.slice(0, 10).map((dep: string) => `  - "${dep}"`).join('\n');
                prompt += '\n\n';
            }
            
            if (config.includeDirs.length > 0) {
                prompt += `**include_dirs 模式:**\n`;
                prompt += config.includeDirs.slice(0, 5).map((dir: string) => `  - "${dir}"`).join('\n');
                prompt += '\n\n';
            }
            
            if (config.defines.length > 0) {
                prompt += `**defines:**\n`;
                prompt += config.defines.map((def: string) => `  - "${def}"`).join('\n');
                prompt += '\n\n';
            }
        }

        prompt += '**请参考以上配置，生成准确的 BUILD.gn 文件。**\n';
        
        return prompt;
    }

    private buildMockPatternsPrompt(mockPatterns: any[]): string {
        let prompt = '\n\n## 📚 从代码库中学习的 Mock 模式\n\n';
        
        const allMocks: any[] = [];
        for (const [projectName, mocks] of mockPatterns) {
            for (const mock of mocks) {
                allMocks.push({ projectName, ...mock });
            }
        }

        if (allMocks.length === 0) {
            return '';
        }

        prompt += `以下是 ${allMocks.length} 个真实项目中的 Mock 实现示例：\n\n`;

        for (let i = 0; i < Math.min(allMocks.length, 3); i++) {
            const mock = allMocks[i];
            prompt += `### Mock 示例 ${i + 1}：${mock.mockClassName} (来自: ${mock.projectName})\n\n`;
            prompt += `- 基类: ${mock.baseClassName}\n`;
            prompt += `- 使用 GMock: ${mock.usesGMock ? '是' : '否'}\n`;
            
            if (mock.overrideMethods.length > 0) {
                prompt += `- Override 方法: ${mock.overrideMethods.slice(0, 5).join(', ')}\n`;
            }
            
            prompt += '\n';
            
            if (mock.exampleSnippet) {
                prompt += `**代码片段：**\n\`\`\`cpp\n${mock.exampleSnippet}\n\`\`\`\n\n`;
            }
        }

        return prompt;
    }

    // ===== 辅助方法 =====

    private getUnitTestPatternCount(): number {
        if (!this.knowledge || !this.knowledge.unitTestPatterns) return 0;
        return this.knowledge.unitTestPatterns.reduce((sum: number, [_, patterns]: [any, any[]]) => sum + patterns.length, 0);
    }

    private getFuzzTestPatternCount(): number {
        if (!this.knowledge || !this.knowledge.fuzzTestPatterns) return 0;
        return this.knowledge.fuzzTestPatterns.reduce((sum: number, [_, patterns]: [any, any[]]) => sum + patterns.length, 0);
    }

    /**
     * 检查知识库是否存在
     */
    public static hasKnowledgeBase(): boolean {
        const knowledgeBasePath = path.join(__dirname, 'codebase-knowledge.json');
        return fs.existsSync(knowledgeBasePath);
    }

    /**
     * 获取知识库信息
     */
    public getKnowledgeBaseInfo(): any {
        if (!this.loaded || !this.knowledge) {
            return null;
        }

        return {
            savedAt: this.knowledge.savedAt,
            projectCount: this.knowledge.projectStructures?.length || 0,
            unitTestPatternCount: this.getUnitTestPatternCount(),
            fuzzTestPatternCount: this.getFuzzTestPatternCount(),
            buildConfigCount: this.knowledge.buildConfigs?.reduce((sum: number, [_, configs]: [any, any[]]) => sum + configs.length, 0) || 0,
            mockPatternCount: this.knowledge.mockPatterns?.reduce((sum: number, [_, mocks]: [any, any[]]) => sum + mocks.length, 0) || 0
        };
    }
}

